// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////

var StringSet = flame.internal.StringSet;

function StringSetTest() {
  this.set_ = new StringSet();
};
registerTestSuite(StringSetTest);

//////////////////////////////////////////////////////
// Tests
//////////////////////////////////////////////////////

StringSetTest.prototype.WrongTypes = function() {
  var set = this.set_;
  var insert = function(item) { return function() { set.insert(item); } };
  var remove = function(item) { return function() { set.remove(item); } };
  var contains = function(item) { return function() { set.contains(item); } };

  var expected = /TypeError.* must be a string/;

  expectThat(insert(), throwsError(expected));
  expectThat(insert(undefined), throwsError(expected));
  expectThat(insert(17), throwsError(expected));
  expectThat(insert(true), throwsError(expected));

  expectThat(remove(), throwsError(expected));
  expectThat(remove(undefined), throwsError(expected));
  expectThat(remove(17), throwsError(expected));
  expectThat(remove(true), throwsError(expected));

  expectThat(contains(), throwsError(expected));
  expectThat(contains(undefined), throwsError(expected));
  expectThat(contains(17), throwsError(expected));
  expectThat(contains(true), throwsError(expected));
};

StringSetTest.prototype.NoElements = function() {
  expectFalse(this.set_.contains(''));
  expectFalse(this.set_.contains('taco'));

  expectThat(this.set_.getElements(), elementsAre([]));
};

StringSetTest.prototype.OneElement = function() {
  this.set_.insert('taco');

  expectTrue(this.set_.contains('taco'));
  expectFalse(this.set_.contains(''));
  expectFalse(this.set_.contains('burrito'));

  expectThat(this.set_.getElements(), elementsAre(['taco']));
};

StringSetTest.prototype.MultipleElements = function() {
  this.set_.insert('taco');
  this.set_.insert('burrito');
  this.set_.insert('enchilada');

  expectTrue(this.set_.contains('taco'));
  expectTrue(this.set_.contains('burrito'));
  expectTrue(this.set_.contains('enchilada'));
  expectFalse(this.set_.contains(''));

  var elements = this.set_.getElements();
  expectThat(elements, elementsAre([_, _, _]));
  expectThat(elements, contains('taco'));
  expectThat(elements, contains('burrito'));
  expectThat(elements, contains('enchilada'));
};

StringSetTest.prototype.SpecialNames = function() {
  expectFalse(this.set_.contains(''));
  expectFalse(this.set_.contains('_'));
  expectFalse(this.set_.contains('constructor'));
  expectFalse(this.set_.contains('hasOwnProperty'));
  expectFalse(this.set_.contains('prototype'));
  expectFalse(this.set_.contains('김치'));

  this.set_.insert('');
  this.set_.insert('_');
  this.set_.insert('constructor');
  this.set_.insert('hasOwnProperty');
  this.set_.insert('prototype');
  this.set_.insert('김치');

  expectTrue(this.set_.contains(''));
  expectTrue(this.set_.contains('_'));
  expectTrue(this.set_.contains('constructor'));
  expectTrue(this.set_.contains('hasOwnProperty'));
  expectTrue(this.set_.contains('prototype'));
  expectTrue(this.set_.contains('김치'));

  var elements = this.set_.getElements();
  expectThat(elements, elementsAre([_, _, _, _, _, _]));
  expectThat(elements, contains(''));
  expectThat(elements, contains('_'));
  expectThat(elements, contains('constructor'));
  expectThat(elements, contains('hasOwnProperty'));
  expectThat(elements, contains('prototype'));
  expectThat(elements, contains('김치'));
};

StringSetTest.prototype.InsertThenRemoveThenInsert = function() {
  var elements;

  this.set_.insert('taco');
  this.set_.insert('hasOwnProperty');
  this.set_.insert('burrito');

  // Remove burrito.
  this.set_.remove('burrito');

  expectTrue(this.set_.contains('taco'));
  expectTrue(this.set_.contains('hasOwnProperty'));
  expectFalse(this.set_.contains('burrito'));

  elements = this.set_.getElements();
  expectThat(elements, elementsAre([_, _]));
  expectThat(elements, contains('taco'));
  expectThat(elements, contains('hasOwnProperty'));

  // Remove hasOwnProperty.
  this.set_.remove('hasOwnProperty');

  expectTrue(this.set_.contains('taco'));
  expectFalse(this.set_.contains('hasOwnProperty'));
  expectFalse(this.set_.contains('burrito'));

  elements = this.set_.getElements();
  expectThat(elements, elementsAre([_]));
  expectThat(elements, contains('taco'));

  // Add both back.
  this.set_.insert('burrito');
  this.set_.insert('hasOwnProperty');

  expectTrue(this.set_.contains('taco'));
  expectTrue(this.set_.contains('hasOwnProperty'));
  expectTrue(this.set_.contains('burrito'));

  elements = this.set_.getElements();
  expectThat(elements, elementsAre([_, _, _]));
  expectThat(elements, contains('taco'));
  expectThat(elements, contains('hasOwnProperty'));
  expectThat(elements, contains('burrito'));
};

StringSetTest.prototype.RemoveUnknownElement = function() {
  this.set_.insert('taco');
  this.set_.insert('burrito');

  this.set_.remove('enchilada');

  expectTrue(this.set_.contains('taco'));
  expectTrue(this.set_.contains('burrito'));
  expectFalse(this.set_.contains('enchilada'));

  var elements = this.set_.getElements();
  expectThat(elements, elementsAre([_, _]));
  expectThat(elements, contains('taco'));
  expectThat(elements, contains('burrito'));
};
